// 其实绝对看过

// // 简写属性名
// let foo = '123';
// let obj = {foo};
// // 健名如果和值是相同名字可以省略
// // let obj = {foo}; ===  let obj ={foo:foo};
// console.log(obj.foo)

// // 简写方法名
// let j = {
//     id:1,
//     show(){
//         console.log(this.id)
//     },
//     hide:function(){
//         console.log(this.id);
//     }
// }
// // show === hide 方法show是省略写法
// j.show();
// j.hide();


// // 属性表达式 在编辑对象  不知道属性的时候会用到 我在小程序做多选的时候用到的
// let obj = {
//     a:1,
//     b:2,
//     c:3,
// }
// // 如果只有一个方法 你想调用里面的属性名
// // 肯定的 obj.a  obj.b obj.c   这不是的写几遍 这不是造成代码的冗余了。
// // 怎么做
// function test(a){
//     console.log(obj[a]);
// }
// test('a');  //1
// test('b');  //2
// test('c');  //3
// // 这样可以做到一个方法 控制所有的


// // 属性表达式还可以怎么玩

// let j = {
//     abc:11,
//     abd:22,
//     abe:33,
//     abf:44,
// }

// console.log(j['ab'+'c'])    //11
// // 字符串拼接   括号里面的
// // j['ab'+'c'] === j['abc']
// // 还可以传入变量   
// let a = 'abd';
// console.log(j[a]);      //22

// 可枚举性
// 就是判断 这个属性 enumerable 是否为 false 怎么获取？
// Object.getOwnPropertyDescriptor
// es5 getOwnPropertyDescriptor 返回某个对象属性的描述对象
// es7 getOwnPropertyDescriptors 返回指定对象所有自身属性（非继承属性）的描述对象。
// 就是返回回实例属性
// 注意 es7 的方法
// 多了 一个 s
// 多了 一个 s
// 多了 一个 s
// 这个方法可以获取
// let obj = {
//     k: '1',
//     get bar() { return 'abc' }
// }
// console.log(Object.getOwnPropertyDescriptor(obj, 'k'),Object.getOwnPropertyDescriptors(obj))
// 这个有什么用了？

// // 扩展运算符
// let abj = {
//     a:1,
//     b:2,
// }
// abj.d = 4;
// let n = {...abj};
// // 等同于   let n = {...abj} === let n = Object.assign({},abj); 这个会在后面讲 一个合并对象的方法

// abj.c = 3;

// // 可以复制对象 如果 abj 修改了 不会影响新的对象
// console.log(abj,n);

// console.log({...'hello'});
// console.log({...['1','2','3']});

// // 除了 数组 和 字符串 会被传成 类数组对象  其他的 都不会被转换
// console.log({...1});                //{}
// console.log({...undefined});        //{}
// console.log({...true});             //{}
// console.log({...null});             //{}


// // 注意 注意 注意  扩展运算符 只能拷贝实例属性 不能拷贝 原型属性
// // 什么是实例属性
// // 实例属性是公开的(public)，可以通过类的实例(或this.)直接访问和修改它。也就是归属实例所有的属性。
// // 什么是原型属性
// // 原型属性又称公共属性，它不属于某个类的实例，而是直接属于某个类。原型属性存在类的原型之中。
// // 很简单 本身函数自带的是实例属性， 存在原型中的 是原型属性
// function pe(){
//     // 实例属性
//     this.x = '测试';
//     this.y = '111';
//     // 原型属性
//     pe.prototype.id = 'id';
// }

// let p1 = new pe();
// let p2 = new pe();
// let p3 = {...new pe()};

// console.log('扩展运算符注意',p3,p2,p1,) //p2 __proto__ 里面没有id 属性


// Object.is
// 数组和对象无法比较，不知道为什么放到对象里面来了，有可能后期还会改进。
// console.log(Object.is([],[]));      //false
// console.log(Object.is({},{}));      //false
// console.log(Object.is('1',1));      //false
// console.log(Object.is(1,1));        //true


// assign
// function pe() {
//     // 实例属性
//     this.x = '测试';
//     this.y = '111';
//     // 原型属性
//     pe.prototype.id = 'id';
// }
// let p1 = new pe();
// let p2 = Object.assign({}, new pe());
// console.log('assigon', p1, p2);

// 拷贝 原型属性的方法 不支持拷贝 不可枚举属性
//  Object.create 创建一个新的 __proto__ 对象  如果不加 就直接加到了 实例属性上的
// Object.getPrototypeOf() 方法返回指定对象的原型（内部[[Prototype]]属性的值）。  返回当前对象 __proto__ 属性
// const clone2 = Object.assign(
//     Object.create(Object.getPrototypeOf(new pe())),
//     new pe()
// );
// console.log(clone2)

// getOwnPropertyDescriptors es7 的方法获取 返回指定对象所有自身属性（非继承属性）的描述对象  可以读取到 非枚举类型
// getPrototypeOf 用于读取一个对象的原型对象
// 可以复制 非枚举类型
// const clone3 = Object.create(
//     Object.getPrototypeOf(new pe()),
//     Object.getOwnPropertyDescriptors(new pe())
// )
// console.log(clone3)

// 设置 为不可枚举属性
// let j = {}
// let k = Object.defineProperty(j, 'k', {
//     enumerable: false,
//     value: 'hello'
// });
// let o = Object.assign({}, {
//     b: 1
// }, k);

// console.log('enumerable', o)
// let o2 = {
//     ...{
//         b: 1
//     },
//     ...k
// }
// console.log('扩展运算符', o2);

// console.log('不可枚举属性k', k, Object.getOwnPropertyDescriptor(j,'k'));

// const clone3 = Object.create(
//     Object.getPrototypeOf(k),
//     Object.getOwnPropertyDescriptors(k)
// )
// console.log(clone3)
// const clone2 = Object.assign(
//     Object.create(Object.getPrototypeOf(k)),
//     k
// );
// console.log(clone2)

// // 证明 assign 和 扩展运算符都不能拷贝 原型属性 和 不可枚举属性



// // 如果拷贝统一一个属性名 会直接覆盖
// let ok1 = {
//     a: 1,
// }
// let ok2 = {
//     a: 2
// }

// let oj1 = {...ok1,...ok2};
// let oj2 = Object.assign({},ok1,ok2);
// console.log(oj1,oj2)

// 注意 如果对象里面还包含对象  assign 只会复制 对象里面的引用
// let j = {
//     k: {
//         a: 1
//     }
// }
// let j1 = Object.assign({}, j);
// let j2 = {...j};
// j.k.a = 2;
// console.log(j1,j2);


// 循环
let jf = function () {
    this.b = 2;
    this.c = 3;
    jf.prototype.h = 'jf'
}
let j = new jf();
// k 是非枚举类型
let obj = Object.defineProperty(j, 'k', {
    enumerable: false,
    value: 'hello'
});

// 可以循环到h 说明 可以获取到原型属性 不能获取到 非枚举属性
for (const i in obj) {
    console.log('forin', i)
}

//不能获取 非枚举属性 不能获取原型属性
console.log('Object.keys',Object.keys(obj))
console.log('Object.values',Object.values(obj))
console.log('Object.entries',Object.entries(obj))

// 可以获取到非枚举类型 不可以获取原型属性
console.log('Object.getOwnPropertyNames',Object.getOwnPropertyNames(obj))

// Symbol 一种ES6 新的原始数据类型，表示独一无二的值 判断是否有这个 Symbol 这个会在下一次讲解
console.log('Object.getOwnPropertySymbols',Object.getOwnPropertySymbols(obj))

// 可以获取到 非枚举类型 不可以获取原型属性
console.log('Reflect.ownKeys',Reflect.ownKeys(obj))

